package com.dissertation.service.impl;

import com.dissertation.annotation.AdminAuth;
import com.dissertation.model.CategoryLeaf;
import com.dissertation.model.CategoryTree;
import com.dissertation.model.auth.Role;
import com.dissertation.pojo.CategoryTreeVO;
import com.dissertation.respository.CategoryTreeRepository;
import com.dissertation.service.CategoryTreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.dissertation.model.auth.Role.ADMIN;
import static com.dissertation.model.auth.Role.STUDENT;
import static com.dissertation.model.auth.Role.TEACHER;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

@Service
public class CategoryTreeImpl implements CategoryTreeService {

    @Autowired
    CategoryTreeRepository categoryTreeRepository;

    @Autowired
    MongoTemplate template;

    @AdminAuth
    @Override
    public String save(CategoryTreeVO categoryTreeVO) {
        String categoryTreeName = categoryTreeVO.getCategoryTreeName();
        CategoryTree categoryTree = new CategoryTree();
        CategoryLeaf categoryLeaf = new CategoryLeaf();
        List<String> list = categoryTreeVO.getRole();
        if(categoryTreeName.equals("0")){
            categoryTree.setUniqueName(categoryTreeVO.getUniqueName());
            //System.out.println(JSON.toJSONString(categoryTree));
            for(String role : list){
                if(role.equals("student")){
                    categoryTree.addRoles(STUDENT);
                }
                else if(role.equals("teacher")){
                    categoryTree.addRoles(TEACHER);
                }
                else if(role.equals("admin")){
                    categoryTree.addRoles(ADMIN);
                }
                else return "error role";
            }
            categoryTree = categoryTreeRepository.save(categoryTree);
            return categoryTree.getId();
        }
        else{
            categoryTree = categoryTreeRepository.findByUniqueName(categoryTreeVO.getCategoryTreeName());

            categoryLeaf.setCategoryLeafName(categoryTreeVO.getUniqueName());
            for(String role : list){
                if(role.equals("student")){
                    categoryLeaf.addRoles(STUDENT);
                }
                if(role.equals("teacher")){
                    categoryLeaf.addRoles(TEACHER);
                }
                if(role.equals("admin")){
                    categoryLeaf.addRoles(ADMIN);
                }
            }
            categoryTree.getCategoryLeaves().add(categoryLeaf);
            categoryTreeRepository.save(categoryTree);
            return categoryTree.getId();
        }


    }


    private List<CategoryTree> findCategoryTree(String name) {
        Aggregation agg =  Aggregation.newAggregation(
                match(Criteria.where("role").elemMatch(Criteria.where("name").is(name))),
                unwind("$categoryLeaves" ),
                match(Criteria.where("categoryLeaves.role").elemMatch(Criteria.where("name").is(name))),
                group("$_id").addToSet("$categoryLeaves").as("categoryLeaves")
                .last("$role").as("role").last("$uniqueName").as("uniqueName")
        );

        AggregationResults<CategoryTree> groupResults
                = template.aggregate(agg, "categoryTree", CategoryTree.class);
        return groupResults.getMappedResults();
    }

    @Override
    public List<CategoryTree> findAllTree(Set<Role>  role) {
        List<CategoryTree> list = new ArrayList<CategoryTree>();
        List<CategoryLeaf> leafList = new ArrayList<>();

        if(role.contains(ADMIN)){
            List<CategoryTree> listAdmin = findCategoryTree(ADMIN.getName());
            list.addAll(listAdmin);
        }
        if(role.contains(TEACHER)){
            List<CategoryTree> listTeacher = findCategoryTree(TEACHER.getName());
            list.addAll(listTeacher);
        }
        if(role.contains(STUDENT)){
            List<CategoryTree> listStudent = findCategoryTree(STUDENT.getName());
            list.addAll(listStudent);
        }
        return list;
    }


}
